package io.kiki.sba.registry.server.clientInterface.store;


import io.kiki.sba.registry.common.model.Tuple;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;

public class _store_<T> implements Store<T> {
    protected final Map<String /*dataInfoId*/, Map<String /*registerId*/, T>> map;
    private final int registerIdCount;

    public _store_(int dataIdCount, int registerIdCount) {
        map = new ConcurrentHashMap<>(dataIdCount);
        this.registerIdCount = registerIdCount;
    }

    @Override
    public Map<String, T> get(String dataInfoId) {
        return map.get(dataInfoId);
    }

    @Override
    public Map<String, T> getOrCreate(String dataInfoId) {
        return map.computeIfAbsent(dataInfoId, k -> new ConcurrentHashMap<>(registerIdCount));
    }

    @Override
    public void forEach(BiConsumer<String, Map<String, T>> consumer) {
        map.forEach(consumer);
    }

    @Override
    public Map<String, Map<String, T>> copyMap() {
        Map<String, Map<String, T>> map = new HashMap<>(this.map.size());
        for (Map.Entry<String, Map<String, T>> entry : this.map.entrySet()) {
            if (!entry.getValue().isEmpty()) {
                map.put(entry.getKey(), new HashMap<>(entry.getValue()));
            }
        }
        return map;
    }

    @Override
    public Tuple<Long, Long> count() {
        long dataInfoIdCount = 0;
        long dataCount = 0;
        for (Map<String, T> map : map.values()) {
            int size = map.size();
            dataCount += size;
            if (size != 0) {
                dataInfoIdCount++;
            }
        }
        return Tuple.of(dataInfoIdCount, dataCount);
    }

    @Override
    public Collection<String> getDataInfoIds() {
        Set<String> set = new HashSet<>(map.values().size());
        for (Map.Entry<String, Map<String, T>> entry : map.entrySet()) {
            if (!CollectionUtils.isEmpty(entry.getValue())) {
                set.add(entry.getKey());
            }
        }
        return set;
    }
}
